from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.decorators import action
from io import BytesIO
import pandas as pd
from django.http import HttpResponse
import datetime
import logging
import json
import openpyxl
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.utils import get_column_letter
import os
import tempfile

from ..models import Host_order, Customer
from ..serializers import HostOrderListSerializer, HostOrderCreateUpdateSerializer
from apps.UMM.models import User

logger = logging.getLogger(__name__)

class HostOrderViewSet(viewsets.ModelViewSet):
    """主机出租订单视图集"""
    queryset = Host_order.objects.all().order_by('-creation_date')
    
    def get_serializer_class(self):
        """根据不同的操作返回不同的序列化器"""
        if self.action in ['list', 'retrieve']:
            logger.info(f"使用HostOrderListSerializer for {self.action}")
            return HostOrderListSerializer
        logger.info(f"使用HostOrderCreateUpdateSerializer for {self.action}")
        return HostOrderCreateUpdateSerializer
    
    def get_queryset(self):
        """实现查询过滤"""
        queryset = super().get_queryset()
        
        # 获取查询参数
        order_number = self.request.query_params.get('order_number', None)
        customer_name = self.request.query_params.get('customer_name', None)
        domain_name = self.request.query_params.get('domain_name', None)
        email = self.request.query_params.get('email', None)
        mobile = self.request.query_params.get('mobile', None)
        customer_wechat = self.request.query_params.get('customer_wechat', None)
        nickname = self.request.query_params.get('nickname', None)
        
        # 记录查询参数
        logger.info(f"HostOrderViewSet查询参数: customer_name={customer_name}, order_number={order_number}")
        
        # 日期范围过滤
        effective_date_start = self.request.query_params.get('effective_date_start', None)
        effective_date_end = self.request.query_params.get('effective_date_end', None)
        expiry_date_start = self.request.query_params.get('expiry_date_start', None)
        expiry_date_end = self.request.query_params.get('expiry_date_end', None)
        
        # 应用过滤条件
        if order_number:
            queryset = queryset.filter(order_number__icontains=order_number)
            
        if customer_name:
            queryset = queryset.filter(customer__customer_name__icontains=customer_name)
            
        if domain_name:
            queryset = queryset.filter(domain_name__icontains=domain_name)
            
        if email:
            queryset = queryset.filter(email__icontains=email)
            
        if mobile:
            queryset = queryset.filter(mobile__icontains=mobile)
            
        if customer_wechat:
            queryset = queryset.filter(customer_wechat__icontains=customer_wechat)
            
        if nickname:
            queryset = queryset.filter(nickname__nickname__icontains=nickname)
        
        # 应用日期范围过滤
        if effective_date_start and effective_date_end:
            queryset = queryset.filter(effective_date__range=[effective_date_start, effective_date_end])
        elif effective_date_start:
            queryset = queryset.filter(effective_date__gte=effective_date_start)
        elif effective_date_end:
            queryset = queryset.filter(effective_date__lte=effective_date_end)
            
        if expiry_date_start and expiry_date_end:
            queryset = queryset.filter(expiry_date__range=[expiry_date_start, expiry_date_end])
        elif expiry_date_start:
            queryset = queryset.filter(expiry_date__gte=expiry_date_start)
        elif expiry_date_end:
            queryset = queryset.filter(expiry_date__lte=expiry_date_end)
            
        return queryset
    
    def create(self, request, *args, **kwargs):
        """重写创建方法，添加客户处理日志"""
        logger.info(f"HostOrderViewSet创建数据: {json.dumps(request.data, default=str)}")
        
        # 记录客户ID
        customer_id = request.data.get('customer')
        logger.info(f"创建主机订单时的客户ID: {customer_id}")
        
        # 确保客户ID是整数
        if customer_id and not isinstance(customer_id, int):
            try:
                # 尝试获取可变的请求数据副本
                if hasattr(request.data, '_mutable'):
                    request.data._mutable = True
                    
                # 转换客户ID为整数
                request.data['customer'] = int(customer_id)
                logger.info(f"已将客户ID转换为整数: {request.data['customer']}")
                
                # 查找客户对象，确认存在性
                try:
                    customer = Customer.objects.get(pk=request.data['customer'])
                    logger.info(f"已找到客户: {customer.customer_name}")
                except Customer.DoesNotExist:
                    logger.error(f"客户ID {request.data['customer']} 不存在")
                    return Response({
                        'code': 400,
                        'message': f"客户ID {request.data['customer']} 不存在",
                        'data': None
                    }, status=status.HTTP_400_BAD_REQUEST)
                    
                # 恢复请求数据的不可变性
                if hasattr(request.data, '_mutable'):
                    request.data._mutable = False
                    
            except (ValueError, TypeError) as e:
                logger.error(f"无法将客户ID转换为整数: {customer_id}, 错误: {str(e)}")
                return Response({
                    'code': 400,
                    'message': f"客户ID格式无效: {customer_id}",
                    'data': None
                }, status=status.HTTP_400_BAD_REQUEST)
        
        # 执行验证和创建
        serializer = self.get_serializer(data=request.data)
        try:
            serializer.is_valid(raise_exception=True)
            logger.info("序列化器验证通过")
        except Exception as e:
            logger.error(f"序列化器验证失败: {str(e)}")
            raise
        
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response({
            'code': 201,
            'message': '主机出租订单创建成功',
            'data': serializer.data
        }, status=status.HTTP_201_CREATED, headers=headers)
    
    def update(self, request, *args, **kwargs):
        """重写更新方法，添加客户处理日志"""
        logger.info(f"HostOrderViewSet更新数据: {json.dumps(request.data, default=str)}")
        
        # 记录客户ID
        customer_id = request.data.get('customer')
        logger.info(f"更新主机订单时的客户ID: {customer_id}")
        
        # 确保客户ID是整数
        if customer_id and not isinstance(customer_id, int):
            try:
                # 尝试获取可变的请求数据副本
                if hasattr(request.data, '_mutable'):
                    request.data._mutable = True
                    
                # 转换客户ID为整数
                request.data['customer'] = int(customer_id)
                logger.info(f"已将客户ID转换为整数: {request.data['customer']}")
                
                # 查找客户对象，确认存在性
                try:
                    customer = Customer.objects.get(pk=request.data['customer'])
                    logger.info(f"已找到客户: {customer.customer_name}")
                except Customer.DoesNotExist:
                    logger.error(f"客户ID {request.data['customer']} 不存在")
                    return Response({
                        'code': 400,
                        'message': f"客户ID {request.data['customer']} 不存在",
                        'data': None
                    }, status=status.HTTP_400_BAD_REQUEST)
                    
                # 恢复请求数据的不可变性
                if hasattr(request.data, '_mutable'):
                    request.data._mutable = False
                    
            except (ValueError, TypeError) as e:
                logger.error(f"无法将客户ID转换为整数: {customer_id}, 错误: {str(e)}")
                return Response({
                    'code': 400,
                    'message': f"客户ID格式无效: {customer_id}",
                    'data': None
                }, status=status.HTTP_400_BAD_REQUEST)
        
        # 执行验证和更新
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        try:
            serializer.is_valid(raise_exception=True)
            logger.info("序列化器验证通过")
        except Exception as e:
            logger.error(f"序列化器验证失败: {str(e)}")
            raise
        
        self.perform_update(serializer)
        
        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
        
        return Response({
            'code': 200,
            'message': '主机出租订单更新成功',
            'data': serializer.data
        })
    
    def retrieve(self, request, *args, **kwargs):
        """重写retrieve方法，添加调试日志和错误处理"""
        try:
            # 记录请求信息
            logger.info(f"HostOrderViewSet retrieve请求参数: {kwargs}")
            
            # 获取对象实例
            instance = self.get_object()
            logger.info(f"获取到Host_order实例: ID={instance.id}, 订单号={instance.order_number}")
            
            # 获取序列化器
            serializer_class = self.get_serializer_class()
            logger.info(f"使用序列化器: {serializer_class.__name__}")
            
            # 序列化实例
            serializer = serializer_class(instance)
            response_data = serializer.data
            
            # 记录返回的数据
            logger.info(f"HostOrderViewSet retrieve返回数据: {json.dumps(response_data, default=str)}")
            
            # 使用与前端期望相符的格式返回
            return Response({
                'code': 200,
                'message': '获取主机出租订单详情成功',
                'data': response_data
            })
            
        except Exception as e:
            logger.error(f"检索主机出租订单失败: {str(e)}", exc_info=True)
            return Response({
                'code': 500,
                'message': f'获取主机出租订单详情失败: {str(e)}',
                'data': None
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=False, methods=['post'])
    def batch_delete(self, request):
        """批量删除主机出租订单"""
        ids = request.data.get('ids', [])
        if not ids:
            return Response({
                'code': 400,
                'message': '未提供要删除的订单ID',
                'data': None
            }, status=status.HTTP_400_BAD_REQUEST)
        
        Host_order.objects.filter(id__in=ids).delete()
        return Response({
            'code': 200,
            'message': '批量删除成功',
            'data': None
        })
    
    @action(detail=False, methods=['get'])
    def export(self, request):
        """导出主机出租订单数据"""
        try:
            queryset = self.get_queryset()
            
            # 创建DataFrame
            df = pd.DataFrame()
            
            # 添加列
            df['订单号'] = [order.order_number for order in queryset]
            df['订单金额'] = [order.order_amount for order in queryset]
            df['出租年限'] = [order.rental_years for order in queryset]
            df['订单来源'] = [order.get_order_source_display() for order in queryset]
            df['网站域名'] = [order.domain_name for order in queryset]
            df['电子邮箱'] = [order.email for order in queryset]
            df['手机号码'] = [order.mobile for order in queryset]
            df['客户微信'] = [order.customer_wechat for order in queryset]
            df['生效日期'] = [order.effective_date for order in queryset]
            df['截至日期'] = [order.expiry_date for order in queryset]
            df['对接人'] = [order.nickname.nickname if order.nickname else '' for order in queryset]
            df['客户名称'] = [order.customer.customer_name if order.customer else '' for order in queryset]
            df['订单备注'] = [order.order_remarks for order in queryset]
            
            # 创建字节流
            output = BytesIO()
            
            # 使用ExcelWriter保存DataFrame到Excel
            with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
                df.to_excel(writer, sheet_name='主机出租订单', index=False)
                
                # 获取workbook和worksheet对象
                workbook = writer.book
                worksheet = writer.sheets['主机出租订单']
                
                # 设置列宽
                for i, col in enumerate(df.columns):
                    col_width = max(df[col].astype(str).map(len).max(), len(col)) + 2
                    worksheet.set_column(i, i, col_width)
            
            # 设置文件指针到开始
            output.seek(0)
            
            # 创建HTTP响应
            response = HttpResponse(
                output.read(),
                content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
            )
            
            # 设置Content-Disposition头以提示浏览器下载文件
            response['Content-Disposition'] = 'attachment; filename="主机出租订单.xlsx"'
            
            return response
            
        except Exception as e:
            logger.error(f"导出主机出租订单数据失败: {str(e)}")
            return Response({
                'code': 500,
                'message': f'导出失败: {str(e)}',
                'data': None
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            
    @action(detail=False, methods=['get'])
    def import_template(self, request):
        """获取导入模板"""
        logger.info("开始生成主机出租导入模板")
        
        try:
            # 使用pandas创建DataFrame
            import pandas as pd
            
            # 创建DataFrame并添加示例数据
            df = pd.DataFrame({
                '订单号*': ['ORD202401001'],
                '客户名称*': ['示例客户'],
                '订单金额*': [1999.99],
                '出租年限*': [1],
                '订单来源*': ['Newbe工作室'],
                '网站域名*': ['example.com'],
                '电子邮箱': ['customer@example.com'],
                '手机号码': ['13800138000'],
                '客户微信': ['exampleuser'],
                '生效日期*': ['2023-01-01'],
                '截至日期*': ['2024-01-01'],
                '对接人': ['张三'],
                '订单备注': ['示例订单备注信息']
            })
            
            logger.info("已创建DataFrame并添加示例数据")
            
            # 创建一个字节流
            output = BytesIO()
            logger.info("已创建字节流")
            
            # 使用ExcelWriter写入到字节流
            with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
                # 将DataFrame写入到Excel文件
                df.to_excel(writer, sheet_name='主机出租订单导入模板', index=False)
                logger.info("已将数据写入到Excel工作表")
                
                # 获取xlsxwriter工作簿和工作表对象
                workbook = writer.book
                worksheet = writer.sheets['主机出租订单导入模板']
                
                # 设置列宽
                for i, col in enumerate(df.columns):
                    max_width = max(df[col].astype(str).map(len).max(), len(col)) + 2
                    worksheet.set_column(i, i, max_width)
                logger.info("已设置列宽")
                
                # 添加第二个工作表，包含说明信息
                info_sheet = workbook.add_worksheet('使用说明')
                info_sheet.write(0, 0, '说明：')
                info_sheet.write(1, 0, '1. 带*的字段为必填项')
                info_sheet.write(2, 0, '2. 订单来源可填写：Newbe工作室、纽币德信息科技、官方网站、其它')
                info_sheet.write(3, 0, '3. 出租年限请填写整数，例如：1, 2, 3')
                info_sheet.write(4, 0, '4. 日期格式：YYYY-MM-DD，例如2023-01-01')
                
                # 添加用户昵称信息
                try:
                    all_users = User.objects.all()
                    user_nicknames = [user.nickname for user in all_users if user.nickname]
                    
                    if user_nicknames:
                        user_list_str = '、'.join(user_nicknames[:10])
                        if len(user_nicknames) > 10:
                            user_list_str += "等"
                        info_sheet.write(5, 0, f'5. 对接人必须填写系统中已存在的用户昵称，如：{user_list_str}')
                        
                        # 添加用户列表工作表
                        users_sheet = workbook.add_worksheet('系统用户列表')
                        users_sheet.write(0, 0, '系统用户昵称列表（用于对接人字段）')
                        for idx, nickname in enumerate(user_nicknames, 1):
                            users_sheet.write(idx, 0, f"{idx}. {nickname}")
                    else:
                        info_sheet.write(5, 0, '5. 对接人必须填写系统中已存在的用户昵称')
                except Exception as e:
                    logger.error(f"获取用户列表失败: {str(e)}")
                    info_sheet.write(5, 0, '5. 对接人必须填写系统中已存在的用户昵称')
                
                logger.info("已添加说明工作表和用户列表")
                
            # 将字节流指针移回起始位置
            output.seek(0)
            logger.info("已将字节流指针移回起始位置")
            
            # 获取字节流的值
            excel_data = output.getvalue()
            logger.info(f"Excel数据大小: {len(excel_data)} 字节")
            
            # 创建HTTP响应
            response = HttpResponse(
                excel_data,
                content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
            )
            response['Content-Disposition'] = 'attachment; filename="主机出租数据导入模板.xlsx"'
            logger.info("已创建HTTP响应")
            
            # 关闭字节流
            output.close()
            logger.info("已关闭字节流")
            
            return response
            
        except Exception as e:
            logger.error(f"生成主机出租订单导入模板失败: {str(e)}", exc_info=True)
            return Response({
                'code': 500,
                'message': f'生成导入模板失败: {str(e)}',
                'data': None
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        
    @action(detail=False, methods=['post'])
    def import_data(self, request):
        """导入主机出租订单数据"""
        logger.info(f"接收到导入请求: {request.data}")
        logger.info(f"上传的文件: {request.FILES}")
        
        # 检查请求中是否有文件
        file = request.FILES.get('file')
        if not file:
            logger.error("未接收到文件")
            return Response({
                'code': 400,
                'message': '未提供文件',
                'data': None
            }, status=status.HTTP_400_BAD_REQUEST)
            
        # 检查文件类型
        if not (file.name.endswith('.xlsx') or file.name.endswith('.xls')):
            logger.error(f"文件格式不正确: {file.name}")
            return Response({
                'code': 400,
                'message': '只支持.xlsx或.xls格式的Excel文件',
                'data': None
            }, status=status.HTTP_400_BAD_REQUEST)
            
        try:
            temp_file_path = None
            
            try:
                # 将上传的文件保存到临时目录
                with tempfile.NamedTemporaryFile(delete=False, suffix=os.path.splitext(file.name)[1]) as temp_file:
                    for chunk in file.chunks():
                        temp_file.write(chunk)
                    temp_file_path = temp_file.name
                
                logger.info(f"文件已保存到临时路径: {temp_file_path}")
                
                # 尝试使用pandas读取Excel文件
                try:
                    df = pd.read_excel(temp_file_path)
                    logger.info(f"成功读取Excel文件，共{len(df)}行数据")
                except Exception as excel_error:
                    logger.error(f"读取Excel文件失败: {str(excel_error)}")
                    return Response({
                        'code': 400,
                        'message': f'无法读取Excel文件: {str(excel_error)}',
                        'data': None
                    }, status=status.HTTP_400_BAD_REQUEST)
            finally:
                # 确保清理临时文件
                if temp_file_path and os.path.exists(temp_file_path):
                    try:
                        os.unlink(temp_file_path)
                        logger.info(f"已删除临时文件: {temp_file_path}")
                    except Exception as delete_error:
                        logger.warning(f"删除临时文件失败: {str(delete_error)}")
            
            # 检查数据是否为空
            if df.empty:
                logger.error("上传的Excel文件不包含任何数据")
                return Response({
                    'code': 400,
                    'message': '上传的Excel文件不包含任何数据',
                    'data': None
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 检查必填列是否存在
            required_columns = ['订单号', '客户名称', '订单金额', '出租年限', '网站域名', '生效日期', '截至日期']
            missing_columns = [col for col in required_columns if col not in df.columns]
            if missing_columns:
                logger.error(f"缺少必填列: {missing_columns}")
                return Response({
                    'code': 400,
                    'message': f'缺少必填列: {", ".join(missing_columns)}',
                    'data': None
                }, status=status.HTTP_400_BAD_REQUEST)
                    
            # 数据处理和导入
            success_count = 0
            error_records = []
            
            for index, row in df.iterrows():
                try:
                    # 检查必填字段
                    empty_fields = []
                    for field in required_columns:
                        if pd.isna(row.get(field)):
                            empty_fields.append(field)
                    
                    if empty_fields:
                        error_records.append({
                            "row": index + 2,  # Excel行号从1开始，且有表头
                            "error": f"以下必填字段不能为空: {', '.join(empty_fields)}"
                        })
                        continue
                    
                    # 尝试转换数据类型
                    try:
                        rental_years = int(row['出租年限'])
                        order_amount = float(row['订单金额'])
                    except (ValueError, TypeError) as type_error:
                        error_records.append({
                            "row": index + 2,
                            "error": f"数据类型错误: 出租年限必须为整数，订单金额必须为数字。详细错误: {str(type_error)}"
                        })
                        continue
                        
                    # 处理客户
                    customer_name = str(row['客户名称']).strip()
                    if not customer_name:
                        error_records.append({
                            "row": index + 2,
                            "error": "客户名称不能为空"
                        })
                        continue
                        
                    customer, created = Customer.objects.get_or_create(
                        customer_name=customer_name,
                        defaults={
                            'customer_source': self._get_source_code(str(row.get('订单来源', 'Newbe工作室')))
                        }
                    )
                    
                    # 处理对接人
                    nickname = None
                    if not pd.isna(row.get('对接人', '')):
                        try:
                            nickname = User.objects.get(nickname=str(row['对接人']).strip())
                        except User.DoesNotExist:
                            # 对接人不存在，记录错误但继续处理
                            error_records.append({
                                "row": index + 2,
                                "error": f"系统中不存在昵称为 '{row['对接人']}' 的用户"
                            })
                            
                    # 处理订单来源
                    order_source = self._get_source_code(str(row.get('订单来源', 'Newbe工作室')))
                    
                    # 处理日期
                    try:
                        effective_date = pd.to_datetime(row['生效日期']).date()
                        expiry_date = pd.to_datetime(row['截至日期']).date()
                    except Exception as e:
                        error_records.append({
                            "row": index + 2,
                            "error": f"日期格式无效: {str(e)}"
                        })
                        continue
                    
                    # 验证日期逻辑
                    if effective_date > expiry_date:
                        error_records.append({
                            "row": index + 2,
                            "error": f"生效日期({effective_date})不能晚于截至日期({expiry_date})"
                        })
                        continue
                        
                    # 创建订单数据
                    host_order = Host_order(
                        order_number=str(row['订单号']),
                        rental_years=rental_years,
                        order_amount=order_amount,
                        order_source=order_source,
                        domain_name=str(row['网站域名']),
                        email=str(row.get('电子邮箱', '')) if not pd.isna(row.get('电子邮箱', '')) else '',
                        mobile=str(row.get('手机号码', '')) if not pd.isna(row.get('手机号码', '')) else '',
                        customer_wechat=str(row.get('客户微信', '')) if not pd.isna(row.get('客户微信', '')) else '',
                        effective_date=effective_date,
                        expiry_date=expiry_date,
                        order_remarks=str(row.get('订单备注', '')) if not pd.isna(row.get('订单备注', '')) else '',
                        customer=customer,
                        nickname=nickname
                    )
                    
                    # 保存订单
                    host_order.save()
                    success_count += 1
                    logger.info(f"成功导入第{index + 2}行数据，订单号: {host_order.order_number}")
                    
                except Exception as e:
                    logger.error(f"导入行 {index + 2} 失败: {str(e)}", exc_info=True)
                    error_records.append({
                        "row": index + 2,
                        "error": str(e)
                    })
                    
            # 返回导入结果
            result = {
                "success_count": success_count,
                "error_count": len(error_records),
                "errors": error_records
            }
            
            logger.info(f"导入结果: 成功={success_count}, 错误={len(error_records)}")
            
            if success_count > 0:
                return Response({
                    'code': 200,
                    'message': f'成功导入{success_count}条记录，失败{len(error_records)}条',
                    'data': result
                })
            else:
                return Response({
                    'code': 400,
                    'message': f'导入失败，共{len(error_records)}条错误记录',
                    'data': result
                }, status=status.HTTP_400_BAD_REQUEST)
                
        except Exception as e:
            logger.error(f"导入主机出租订单数据失败: {str(e)}", exc_info=True)
            return Response({
                'code': 500,
                'message': f'导入失败: {str(e)}',
                'data': None
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            
    def _get_source_code(self, source_name):
        """将订单来源名称转换为代码"""
        source_mapping = {
            'Newbe工作室': 0,
            '纽币德信息科技': 1,
            '官方网站': 2,
            '其它': 3
        }
        return source_mapping.get(source_name, 0)  # 默认返回Newbe工作室 

    def list(self, request, *args, **kwargs):
        """重写list方法，使用一致的响应格式"""
        try:
            # 调用父类的list方法
            queryset = self.filter_queryset(self.get_queryset())

            # 分页
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                result = self.get_paginated_response(serializer.data)
                data = result.data
            else:
                serializer = self.get_serializer(queryset, many=True)
                data = serializer.data

            # 使用一致的响应格式
            return Response({
                'code': 200,
                'message': '获取主机出租订单列表成功',
                'data': data
            })
            
        except Exception as e:
            logger.error(f"获取主机出租订单列表失败: {str(e)}", exc_info=True)
            return Response({
                'code': 500,
                'message': f'获取主机出租订单列表失败: {str(e)}',
                'data': None
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) 